import errors from "./errors";
import * as fs from "fs";
import * as yaml from "yaml";
import * as path from "path";

export interface Config {
    port: number;
    conns: { [name: string]: string }
}

export interface DatabaseConfig {
    conn: string;
    tables: { [name: string]: { [columnName: string]: ColumnConfig } }
}

export type ColumnConfig = { type?: string, primary?: boolean };

export function loadConfig(configPath: string) {
    if (!fs.existsSync(configPath))
        throw errors.pathNotExists(configPath);

    let content = fs.readFileSync(configPath, "utf8");
    let config: Config = yaml.parse(content);
    if (config.port == null)
        throw errors.configMissingField("port");

    if (typeof config.port !== "number")
        throw errors.configInvalidType("port", "number");

    if (config.conns == null)
        config.conns = {};

    return config;
}

let config: Config | null = null;
export function getConfig() {
    if (config === null) {
        let configPath = path.join(__dirname, "../config.yaml");
        config = loadConfig("config.yaml");
    }

    return config;
}

export function getDatabaseConfigPath() {
    let databaseConfigPath = path.join(__dirname, "../configs/database");
    if (!fs.existsSync(databaseConfigPath))
        throw errors.pathNotExists(databaseConfigPath);

    return databaseConfigPath;
}

export function loadDatabaseConfig(name: string) {
    let databaseConfigPath = getDatabaseConfigPath();
    let filePath = path.join(databaseConfigPath, `${name}.yaml`);
    if (!fs.existsSync(filePath))
        throw errors.pathNotExists(filePath);

    let content = fs.readFileSync(filePath, "utf8");
    let config = yaml.parse(content) as DatabaseConfig;
    for (let tableName in config.tables) {

        if (tableName.toLowerCase() !== tableName)
            throw errors.tableNameShouldBeLowerCase(tableName);

        tableName = tableName.toLowerCase();
        let table = config.tables[tableName];
        for (let columnName in table) {
            if (columnName.toLowerCase() !== columnName)
                throw errors.columnNameShouldBeLowerCase(columnName);

            columnName = columnName.toLowerCase();
            let column = table[columnName];
            if (typeof column === "string" || column == null) {
                table[columnName] = {};
            }
        }
    }

    return config;
}